home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Collections: R-H-S
/
R-H-S Tools 19 (19xx)(Reiner Hobbold Software)(DE)(PD).zip
/
R-H-S Tools 19 (19xx)(Reiner Hobbold Software)(DE)(PD).adf
/
MyMenu
/
MyMenu.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-08-19
|
9KB
|
315 lines
/* Copyright ) Darin Johnson, 1989 */
/* */
/* Permission is granted to use */
/* this program and to freely copy */
/* it and/or source code as long */
/* as these notices remain. */
/* No charges for these copies may */
/* be made, except for handling */
/* and distribution fees. */
/* This program puts customized menus into the WorkBench menubar. */
/* The program is split up into two parts, MyMenu and MyMenu-Handler. */
/* This section is MyMenu and it initializes and starts up a process */
/* to run MyMenu-Handler, and then terminates. MyMenu also terminates */
/* and cleans up after the suprocess. MyMenu will parse the users */
/* menus, initialize data to be passed to MyMenu-Handler, and start */
/* up MyMenu-Handler. MyMenu-Handler does very little memory */
/* allocation in order to save space, so MyMenu does allocation and */
/* freeing for it. */
#include <exec/types.h>
#include <exec/memory.h>
#include <graphics/gfxbase.h>
#include <intuition/intuitionbase.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <functions.h>
#include <stdio.h>
#include <ctype.h>
#include "mymenu.h"
static char *copyright = "Copyright ) Darin Johnson, 1989";
/* actually, I don't know if it will work under Lattice */
#ifdef AZTEC_C
#define strcmp _BUILTIN_strcmp
#define strcpy _BUILTIN_strcpy
#define strlen _BUILTIN_strlen
#endif
struct IntuitionBase *IntuitionBase = NULL;
struct GfxBase *GfxBase = NULL;
extern int menu_num;
/* this is the data structure that we use to pass data to MyMenu-Handler */
struct MMData *MM;
char do_quit;
int i;
/* make (and allocate) a copy of the passed string */
char *copystr(str)
char *str;
{
char *newstr;
newstr = AllocMem(strlen(str)+1, MEMF_PUBLIC);
strcpy(newstr, str);
return newstr;
}
/* strcmp, ignoring case */
#define UPPER(c) (islower(c)?toupper(c):(c))
int stricmp(s, t)
char *s, *t;
{
for ( ; UPPER(*s) == UPPER(*t); s++, t++)
if (*s== NULL)
return 0;
return UPPER(*s) - UPPER(*t);
}
/* Find the workbench window - I'm sure there's a better way... */
struct Window *find_workbench() {
struct Screen *scr;
struct Window *win;
ULONG ilock;
ilock = LockIBase(0L); /* just so's things don't change on us */
for (scr = IntuitionBase->FirstScreen; /* find WB Screen */
scr && strcmp(scr->DefaultTitle, "Workbench Screen");
scr=scr->NextScreen);
if (!scr) {
UnlockIBase(ilock);
printf("That's odd... I can't find the workbench screen...\n");
_abort(2000);
}
for (win=scr->FirstWindow; win; win = win->NextWindow)
if (win->Flags & WBENCHWINDOW) break;
UnlockIBase(ilock);
return win;
}
/* open a library */
APTR *open_lib(name, rev)
char *name;
long rev;
{
APTR *lib;
if ((lib = (APTR*)OpenLibrary(name, rev)) == NULL) {
printf("Can't open %s (rev=%d\n", name, rev);
_abort(1000);
}
return lib;
}
/* make a copy of our CLI path. We also convert BCPL stuff. */
copy_path() {
register struct Path *oldpath, *newpath, *tmppath;
struct CommandLineInterface *cli;
struct Process *pr;
pr = (struct Process *)FindTask(NULL);
cli = (struct CommandLineInterface *)BADDR(pr->pr_CLI);
newpath = MM->CLI_path = NULL;
for (oldpath = (struct Path *)BADDR(cli->cli_CommandDir); oldpath;
oldpath = (struct Path *) BADDR(oldpath->path_Next)) {
tmppath = (struct Path *)AllocMem(sizeof(struct Path), MEMF_PUBLIC);
if (!MM->CLI_path) {
MM->CLI_path = tmppath;
} else {
newpath->path_Next = tmppath; /* we don't convert to BCPL */
}
newpath = tmppath;
tmppath->path_Next = NULL;
tmppath->path_Lock = DupLock(oldpath->path_Lock);
}
}
/* free up the space used by the copy of the CLI path */
free_path() {
register struct Path *tmp, *path;
/* clean out copy of path */
path = MM->CLI_path;
MM->CLI_path = NULL;
while (path) {
tmp = path;
path = path->path_Next;
UnLock(tmp->path_Lock);
FreeMem(tmp, sizeof(struct Path));
}
}
/* Initialize and load up the handler process, or update the menus */
/* for an existing handler. */
add_handler() {
ULONG ilock;
if (MM) {
/* remove old menus and update */
printf("Updating menus -- ");
fflush(stdout);
/* coordinate with handler */
MM->parent_task = FindTask(NULL);
MM->parent_sig = AllocSignal(-1L);
Signal(MM->handler_task, SIGBREAKF_CTRL_D);
Wait(1 << MM->parent_sig);
/* clean old stuff up */
free_menus();
ilock = LockIBase(0L);
menu_num = 0;
for (MM->prev_menu = MM->WBWindow->MenuStrip;
MM->prev_menu->NextMenu;
MM->prev_menu=MM->prev_menu->NextMenu)
menu_num++;
UnlockIBase(ilock);
/* get new menus */
if (!parse_menus()) {
do_quit = TRUE;
return;
}
/* let handler know it can continue */
Signal(MM->handler_task, SIGBREAKF_CTRL_D);
printf("ok\n");
return;
}
/* create a new handler */
printf("Installing MyMenu -- ");
fflush(stdout);
/* get area to pass data in */
MM = (struct MMData *)AllocMem(sizeof(struct MMData), MEMF_PUBLIC|MEMF_CLEAR);
MM->WBWindow = find_workbench();
if (MM->WBWindow==NULL) {
printf("Can't find Workbench...\n");
do_quit = TRUE;
return;
}
/* we need to find out what menu number ours start at */
ilock = LockIBase(0L);
menu_num = 0;
for (MM->prev_menu = MM->WBWindow->MenuStrip;
MM->prev_menu->NextMenu;
MM->prev_menu=MM->prev_menu->NextMenu)
menu_num++;
UnlockIBase(ilock);
/* read in user's menus */
if (!parse_menus()) {
do_quit = TRUE;
return;
}
MM->port.mp_Flags = PA_IGNORE; /* we'll get msg's from do_wbrun */
MM->port.mp_Node.ln_Pri = 0;
MM->port.mp_Node.ln_Type = NT_MSGPORT;
MM->port.mp_Node.ln_Name = copystr(MYMENU_NAME);
NewList(&MM->port.mp_MsgList);
/* load in handler */
MM->segment = LoadSeg("l:MyMenu-Handler");
if (!MM->segment)
MM->segment = LoadSeg("MyMenu-Handler");
if (!MM->segment) {
printf("Can't find L:MyMenu-Handler\n");
do_quit = TRUE;
return;
}
/* add to port list so that handler can find it */
AddPort(&MM->port);
MM->parent_task = FindTask(NULL);
MM->parent_sig = AllocSignal(-1L);
copy_path();
CreateProc(MYMENU_NAME, 0, MM->segment, STACK);
/* handshake so that we know it got started ok */
Wait(1 << MM->parent_sig);
FreeSignal(MM->parent_sig);
if (MM->error_code) {
printf("Handler error (%d)\n", MM->error_code);
do_quit = TRUE;
} else {
printf("ok - %s\n", VERSION);
}
}
/* shutdown and clean up after handler */
remove_handler() {
if (!MM)
return;
printf("removing -- ");
fflush(stdout);
if (MM->segment != NULL) {
MM->parent_task = FindTask(NULL);
MM->parent_sig = AllocSignal(-1L);
Signal(MM->handler_task, SIGBREAKF_CTRL_C);
/* wait until handler cleans up */
/* (don't advertise that we catch ^C - for emergency use only) */
Wait(1 << MM->parent_sig);
FreeSignal(MM->parent_sig);
if (MM->error_code != ERR_OK) {
/* we can get an error if there are outstanding WB processes */
printf("Leaving handler in place...\n");
return;
}
RemPort(&MM->port);
UnLoadSeg(MM->segment);
}
/* this is done here, not in handler... */
free_path();
free_menus();
if (MM->port.mp_Node.ln_Name)
FreeMem(MM->port.mp_Node.ln_Name, strlen(MM->port.mp_Node.ln_Name)+1);
FreeMem(MM, sizeof(struct MMData));
printf("done\n");
}
/* Close up libraries and exit. Having a routine named _abort() is */
/* handy for use with SDB, otherwise, I would have a better name. */
_abort(st)
int st;
{
if (IntuitionBase)
CloseLibrary(IntuitionBase);
if (GfxBase)
CloseLibrary(GfxBase);
exit(st);
}
main(argc, argv)
int argc;
char *argv[];
{
IntuitionBase = (struct IntuitionBase *)open_lib("intuition.library", 0L);
GfxBase = (struct GfxBase *)open_lib("graphics.library", 0L);
do_quit=FALSE;
for (i=1; i<argc; i++) {
if (stricmp(argv[i], "QUIT")==0) {
do_quit=TRUE;
continue;
}
/* no other options yet */
printf("Usage: MyMenu [quit]\n");
_abort(10);
}
/* find shared data (if it exists) */
MM = (struct MMData *)FindPort(MYMENU_NAME);
if (do_quit == FALSE) {
add_handler();
};
if (do_quit==TRUE) { /* note that this isn't an 'else' */
remove_handler();
}
_abort(0);
}